package com.cssl.gulimall.auth.controller;

import com.alibaba.fastjson.TypeReference;
import com.cssl.common.constant.auth.AuthConstant;
import com.cssl.common.exception.BizCodeEnume;
import com.cssl.common.utils.R;
import com.cssl.common.vo.auth.MemberResponseVO;
import com.cssl.common.vo.auth.UserForgetVO;
import com.cssl.common.vo.auth.UserLoginVO;
import com.cssl.common.vo.auth.UserRegisterVO;
import com.cssl.gulimall.auth.feign.MemberFeignService;
import com.cssl.gulimall.auth.feign.ThirdPartFeignService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Controller
public class LoginController {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ThirdPartFeignService thirdPartFeignService;
    @Autowired
    private MemberFeignService memberFeignService;

    @GetMapping("/sms/sendCode")
    @ResponseBody
    public R sendCode(@RequestParam(name = "phone",required = true) String phone){
        //判断60秒间隔 防刷
        String _code = redisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX+phone);
        if(StringUtils.isNotBlank(_code) && (System.currentTimeMillis()-Long.parseLong(_code.split("_")[1]))<60000){
            //调用接口间隔小于60秒
            return R.error(BizCodeEnume.SMS_CODE_EXCEPTION);
        }

        //生成验证码
        String code = UUID.randomUUID().toString().substring(0,5);
        //存入缓存  并记录时间戳
        redisTemplate.opsForValue().set(AuthConstant.SMS_CODE_CACHE_PREFIX+phone,code+"_"+System.currentTimeMillis(),60, TimeUnit.SECONDS);
        //发送验证码
        thirdPartFeignService.sendCode(phone,code);
        return R.ok();
    }

    @PostMapping("/register")
    public String register(@Valid UserRegisterVO user, BindingResult result, RedirectAttributes attributes){
        //参数校验
        if(result.hasErrors()){
            Map<String,String> errors = new HashMap<>();
            result.getFieldErrors().forEach(error->errors.put(error.getField(),error.getDefaultMessage()));
            //封装错误信息  返回前台
            attributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.gulimall.com/reg.html";

        }
        //验证码校验
        String code = user.getCode();
        String redisCode = redisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + user.getPhone());
        if(StringUtils.isEmpty(redisCode)){
            //验证码过期
            Map<String,String> errMap = new HashMap<>();
            errMap.put("code","验证码失效");
            attributes.addFlashAttribute("errors",errMap); //flash,session中的数据只使用一次
            return "redirect:http://auth.gulimall.com/reg.html";
        }
        String getCode = redisCode.split("_")[0];
        if(!code.equals(getCode)){
            //验证码错误
            Map<String,String> errMap = new HashMap<>();
            errMap.put("code","验证码错误");
            System.out.println("验证码：" + getCode + "===验证码错误");
            attributes.addFlashAttribute("errors",errMap);
            return "redirect:http://auth.gulimall.com/reg.html";
        }
        //远程调用 注册
        redisTemplate.delete(AuthConstant.SMS_CODE_CACHE_PREFIX+user.getPhone());
        R r = memberFeignService.register(user);
        if(r.getCode()==0){
            //注册成功  跳转登录页面
            return "redirect:http://auth.gulimall.com/login.html";
        }else {
            Map<String,String> errMap = new HashMap<>();
            errMap.put("msg",r.getData("msg",new TypeReference<String>(){}));
            attributes.addFlashAttribute("errors",errMap);
            return "redirect:http://auth.gulimall.com/reg.html";
        }
    }

    /*
        登陆接口
     */
    @PostMapping("/login")
    public String login(UserLoginVO user, RedirectAttributes attributes, HttpSession session){
        //远程调用登录
        R r = memberFeignService.login(user);
        if(r.getCode() == 0){
            //登录成功，设置session
            MemberResponseVO data = r.getData(new TypeReference<MemberResponseVO>(){});
            session.setAttribute(AuthConstant.LOGIN_USER,data);
            return "redirect:http://gulimall.com";
        }else {
            //登录失败，封装异常信息重定向返回
            Map<String, String> errors = new HashMap<>();
            errors.put("msg",r.getData("msg",new TypeReference<String>(){}));
            attributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }

    /**
     * 退出
     */
    @GetMapping("/loginOut")
    public String loginOut(HttpSession session){
        session.removeAttribute(AuthConstant.LOGIN_USER);
        return "redirect:http://auth.gulimall.com/login.html";
    }

    /**
     *忘记密码
     */
    @PostMapping("/forget")
    public String forget(@Valid UserForgetVO userForgetVO, BindingResult result, RedirectAttributes attributes){
        if(result.hasErrors()){
            Map<String,String> errors = new HashMap<>();
            result.getFieldErrors().forEach(error->errors.put(error.getField(),error.getDefaultMessage()));
            attributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.gulimall.com/forget.html";
        }
        //判断该号码是否绑定账户
        R r = memberFeignService.hasPhoneBiding(userForgetVO.getPhone());
        if(r.getCode() != 0){
            //该号码没有绑定账户
            Map<String,String> errMap = new HashMap<>();
            errMap.put("phone","该号码没有绑定账户");
            attributes.addFlashAttribute("errors",errMap);
            return "redirect:http://auth.gulimall.com/forget.html";
        }
        //验证码校验
        String code = userForgetVO.getCode();
        String redisCode = redisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + userForgetVO.getPhone());
        if(StringUtils.isEmpty(redisCode)){
            //验证码过期
            Map<String,String> errMap = new HashMap<>();
            errMap.put("code","验证码失效");
            attributes.addFlashAttribute("errors",errMap);
            return "redirect:http://auth.gulimall.com.forget.html";
        }
        String getCode = redisCode.split("_")[0];
        if(!code.equals(getCode)){
            //验证码错误
            Map<String,String> errMap = new HashMap<>();
            errMap.put("code","验证码错误");
            attributes.addFlashAttribute("errors",errMap);
            return "redirect:http://auth.gulimall.com.forget.html";
        }
        //远程调用  更改密码
        redisTemplate.delete(AuthConstant.SMS_CODE_CACHE_PREFIX+userForgetVO.getPhone());
        r = memberFeignService.changePwd(userForgetVO);
        if(r.getCode() == 0){
            //修改成功 跳转登录页面
            return "redirect:http://auth.gulimall.com/login.html";
        }else {
            Map<String,String> errMap = new HashMap<>();
            errMap.put("msg",r.getData("msg",new TypeReference<String>(){}));
            attributes.addFlashAttribute("errors",errMap);
            return "redirect:http://auth.gulimall.com/forget.html";
        }
    }
}
